package com.college.common.utils.security;

import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson2.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 小C工作室
 * @date 2022/10/21 16:30
 * @project manager_system_server_axh
 * @company 韦伯创想
 * @description
 */
public class MsydAesApiEncrypt {

	public final static String AES_CBC_PKCS5Padding = "AES/CBC/PKCS5Padding";
	private static final String ENCODING = "utf-8";
	private static final String KEY_ALGORITHM = "AES";

	public static void main(String[] args) {
		String timestamp = String.valueOf(System.currentTimeMillis());//生成时间戳
		String ivKey = genTimestampIV(timestamp); // 生成 Aes 加密iv向量
		String aesKey = "edgVen9shfddsh%V"; //
		System.out.println("ivKey：" + ivKey);
		Map<String, String> map = new HashMap<>();
		String cardNum = DigestUtil.md5Hex("500212199793941312");
		String mobile = DigestUtil.md5Hex("1666345615026");
		String signaturePhoneCard = DigestUtil.md5Hex("13524326124500212199793941312");
		map.put("signatureCard", cardNum);
		map.put("signaturePhone", mobile);
		map.put("signaturePhoneCard", signaturePhoneCard);

		String json = JSONObject.toJSONString(map);
		System.out.println("加密前明文：" + json);
		String enData = cbcEncrypt(json, aesKey, ivKey);

		Map<String, String> reqMap = new HashMap<>();
		reqMap.put("appChannel", "minsheng");
		reqMap.put("enData", enData);
		reqMap.put("timestamp", timestamp); // 时间戳13位,用于aes加密向量 iv 规则
		System.out.println("enData = " + enData);
		System.out.println("加密后报文：" + JSONObject.toJSONString(reqMap));
		System.out.println("解密后内容：" + cbcDecrypt(enData, aesKey, ivKey));

	}

	/**
	 * 根据时间戳13位，生成aes cbc 加密向量 vi
	 * 生成规则先把时间戳反向，用零补足16位
	 *
	 * @param timestamp
	 * @return
	 */
	public static String genTimestampIV(String timestamp) {
		return StringUtils.reverse(timestamp) + "000";
	}

	/**
	 * AES 加密操作
	 *
	 * @param content 待加密内容
	 * @param key     加密密码
	 * @return 返回Base64转码后的加密数据
	 */
	public static String cbcEncrypt(String content, String key, String ivKey) {
		try {
			byte[] contentBytes = content.getBytes(ENCODING);
			byte[] keyBytes = key.getBytes(ENCODING);
			SecretKeySpec keySpec = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
			Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5Padding);// 创建密码器
			//指定一个初始化向量 (Initialization vector，IV)， IV 必须是16位
			byte[] ivBytes = ivKey.getBytes(ENCODING);
			cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(ivBytes));
			byte[] encryptByte = cipher.doFinal(contentBytes);
			return Base64.encodeBase64String(encryptByte);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * AES 解密操作
	 *
	 * @param content
	 * @param key
	 * @return
	 */
	public static String cbcDecrypt(String content, String key, String ivKey) {
		try {
			byte[] contentBytes = Base64.decodeBase64(content);
			byte[] keyBytes = key.getBytes(ENCODING);
			SecretKeySpec keySpec = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
			Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5Padding);// 创建密码器
			//指定一个初始化向量 (Initialization vector，IV)， IV 必须是16位
			byte[] ivBytes = ivKey.getBytes(ENCODING);
			cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ivBytes));
			byte[] dataBytes = cipher.doFinal(contentBytes);
			return new String(dataBytes, ENCODING);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

}
